#include "KeyRecommander.h"
#include "Singleton.h"
#include "EditDistance.h"
#include <sstream>
using std::ostringstream;

KeyRecommander::KeyRecommander(const string &sought, TcpConnectionPtr con)
:_pDictionary(Singleton<Dictionary>::getInstance("data"))
,_en_dict(_pDictionary->getEnDict())
,_en_index(_pDictionary->getEnIndex())
,_cn_dict(_pDictionary->getCnDict())
,_cn_index(_pDictionary->getCnIndex())
,_sought(sought)
,_con(con)
{

}

// 将候选词加入队列
void KeyRecommander::doQuery(){
    if(is_eng(_sought)){
        searchEn();
    }
    else{
        searchCn();
    }
}

// 输出结果
void KeyRecommander::response(){
    ostringstream oss;
    for(int i = 0; i < 10 && !_prique.empty(); ++i){
        oss << _prique.top()._word;
        oss << endl;
        _prique.pop();
    }

    while(!_prique.empty()){
        _prique.pop();
    }
    if(oss.str().size() == 0){
        oss << "no result\n";
    }
    _con->sendInLoop(oss.str());
}

void KeyRecommander::searchCn(){
    // 获取下标集合
    // 1 中文分词
    unique_ptr<SplitTool> sp(new SplitToolUTF8());
    vector<string> cuted = sp->cut(_sought);
    size_t degree = cuted.size() / 5; // 匹配度几分之几
    // 2 取交集
    map<size_t, size_t> cnt_idx; 
    set<size_t> candidateIdx;
    for(auto it_cuted=cuted.begin(); it_cuted!=cuted.end(); ++it_cuted){
        if(_cn_index.find(*it_cuted) != _cn_index.end()){
            for(auto &elem:_cn_index[*it_cuted]){
               if(++cnt_idx[elem] > degree){
                    candidateIdx.insert(elem);
               } 
            }
        }
    }
    
    cout << candidateIdx.size() << " results:" << endl;
    // 3 存储判断距离和频率，插入优先级队列，输出最多10
    while(!_prique.empty()){
        _prique.pop();
    }
    for(auto &elem: candidateIdx){
        CandidateResult candidate;
        candidate._dist = EditDistance().editDistance(_sought, _cn_dict[elem].first);
        candidate._freq = _cn_dict[elem].second;
        candidate._word = _cn_dict[elem].first;
        _prique.push(candidate);
    }
}

void KeyRecommander::searchEn(){
    set<string> cuted;
    for(auto &elem: _sought){
        if(isalpha(elem)){
            if (isupper(elem))
            {
                elem = tolower(elem);
            }
            char c[2] = {0};
            c[0] = elem;
            cuted.insert(c);
        }
    }
    map<size_t, size_t> cnt_idx;
    for(auto &elem: cuted){
        for(auto iter=_en_index[elem].begin(); iter!=_en_index[elem].end(); ++iter){
            cnt_idx[*iter]++;
        }
    }
    set<size_t> candidateIdx;
    for(auto &elem: cnt_idx){
        if(elem.second > cuted.size() - 2){
            candidateIdx.insert(elem.first);
        }
    }
    cout << candidateIdx.size() << " results:" << endl;
    // 3 存储判断距离和频率，插入优先级队列，输出最多10
    while(!_prique.empty()){
        _prique.pop();
    }
    for(auto &elem: candidateIdx){
        CandidateResult candidate;
        candidate._dist = EditDistance().editDistance(_sought, _en_dict[elem].first);
        candidate._freq = _en_dict[elem].second;
        candidate._word = _en_dict[elem].first;
        _prique.push(candidate);
    }
}

bool KeyRecommander::is_eng(const string& str){
    if ((str[0] >= 0x41 && str[0] <= 0x5a) || (str[0] >= 0x61 && str[0] <= 0x7a)){
        return true;
    }
    return false;
}